#
# WM - World Model, the guts and bolts of WMI
#
# The main point here is to organize all of the information we know about the world
#  about a certain cycle in a way that can be most easily interpreted by the WMI
#  class, thought which the rest of the code will be working
#

__all__ = ['conlib', 'robomath']

import sys
import conlib

class cycle:
    "A moment of the game"
    def __init__(self, sense_body, gamestate):
        self.sense_body = sense_body
        self.gamestate = gamestate
        self.vision = None
    
    def addSight(self, see):
        self.vision = see


"A model of the World According to Robo"
                   # this information stays constant throughout the games
server_param = {}  # server_param info from server
player_param = {}  # player_param info from server
player_type = []   # player_type-s info from server

teamname = None    # String set in init()
unum = None        # player #
side = None        # 'l' or 'r'

current = cycle([0,0], "start")
                        # cycle of current cycle
        
history = {}        # a record of every cycle this game
memory = []        # a record of the last memsize Contexts
memsize = 25        # the number of last Contexts some WMI
                        #   decisions are made off of

context = conlib.Context()
                        # our preception of the world around us.
                                    
def init(init, team):
    "Takes (init *) command from server and pulls info, inits team name"

    info = init[0].split(" ")
    
    if info[0] == '(error':
        print "Error (WM.world::init) encountered on init response from server:"
        print init
        return False
        
    side = info[1]
    unum = int(info[2])
    game_state = info[3]
    teamname = team
    return True    
                
def report(message):
    "Records a message passed in from L1"
    
    apply({
        "sense_body":iSense,
        "see":iSee,
        "server_param":iServer,
        "player_param":iPlayerParam,
        "player_type":iPlayerType,
        "hear":iHear,
    }.get(message[0],
        (lambda x: sys.stdout.write("Unhandled message: "+str(x)))), (message,))
            
def iSee(see):
    """
    Input: (see *) command from server in list form
    Output: updates information we know about the world
    Note: it is safe to assume that iSense has been run before this at least once
    """
    current.addSight(see)
    context.update_sight(self)

def iSense(sense_body):
    # This method is called once every cycle
    """ takes a sense_body list and organizes it
    Input: sense_body list
    Output: info is updated
    Note: info is a dictionary of LISTS, as some keys, such as 'view_mode'
      have more than one piece of information associated with them
    Note 2: a sense_body is recieved, and when this function is called, is 
      the client's definition of a new cycle.
    """
    # don't think we'll need this, but you know, just in case...
    if int(current.sense_body[1]) - int(sense_body[1]) > 1:
        print "WARINING: Missed some rounds, cycle is %s, new sense_body[1] is %s" % (cycle, sense_body[1])
    
    # create a new WM, set it as the current one, add to history dict
    current = history[int(sense_body[1])] = cycle(sense_body, game_state)
    
    # update the context
    context.update(self)

def iServer(server_param):
    """ takes (server_param *) command and pulls info
    Input: (server_param *) command from server
    Output: server contains the parameters
    """
    for x in server_param[1:]:
        server_param[x[0]] = x[1]
    
def iPlayerType(player_type):
    """ takes (player_type *) command and pulls info
    Input: (player_type *) command from server
    Output: playerType is populated
    Note: this function assumes that players are given in order. If not, it will
        not be the case that playerType[x]['id'] = x, I haven't
        seen this happen, but it's possible, I guess...
    """
    newtype = {}
    for x in player_type[1:]:
        newtype[x[0]] = x[1]
    player_type.append(newtype)

def iPlayerParam(player_param):
    """ takes (player_param *) command and pulls info
    Input: (player_param *) command from server
    Output: param is populated
    """
    for x in player_param[1:]:
        print x
        player_param[x[0]] = x[1]

def iHear(hear):
    print hear
    
